package com.moonLight.weblog.common.domain.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.moonLight.weblog.common.config.InsertBatchMapper;
import com.moonLight.weblog.common.domain.dos.WikiCatalogDO;
import com.moonLight.weblog.common.enums.WikiCatalogLevelEnum;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.jdbc.SQL;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

import static com.baomidou.mybatisplus.extension.toolkit.SimpleQuery.selectList;
import static org.apache.ibatis.jdbc.SqlBuilder.INSERT_INTO;

/**
 * @author moonLight
 * @description: InsertBatchMapper 接口，后续对目录操作时，需要使用到批量插入。
 * @date 2019/12/29 16:07
 */
public interface WikiCatalogMapper extends BaseMapper<WikiCatalogDO> {


    /**
     * 查询某个知识库下所有目录
     *
     * @param wikiId
     * @return
     */
    default List<WikiCatalogDO> selectByWikiId(Long wikiId) {
        return selectList(Wrappers.<WikiCatalogDO>lambdaQuery()
                .eq(WikiCatalogDO::getWikiId, wikiId)
        );
    }

    /**
     * 删除知识库
     *
     * @param wikiId
     * @return
     */
    default int deleteByWikiId(Long wikiId) {
        return delete(Wrappers.<WikiCatalogDO>lambdaQuery()
                .eq(WikiCatalogDO::getWikiId, wikiId));
    }

    /**
     * 批量插入目录
     * @param batchList
     * @return
     */
    @InsertProvider(type = SqlProvider.class, method = "insertBatchSomeColumn")
    int insertBatchSomeColumn(@Param("list") List<WikiCatalogDO> batchList);


    class SqlProvider {
        private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        /**
         * 批量插入目录 根据传入的参数进行拼接sql语句
         * @param list
         * @return
         */
        public String insertBatchSomeColumn(List<WikiCatalogDO> list) {
            if (list == null || list.isEmpty()) {
                return "SELECT 1";
            }

            try {
                StringBuilder sql = new StringBuilder();
                sql.append(new SQL() {{
                    INSERT_INTO("t_wiki_catalog");
                    INTO_COLUMNS("wiki_id", "article_id", "title", "level", "parent_id", "sort", "create_time", "update_time", "is_deleted");
                }}.toString());

                sql.append(" VALUES ");
                for (int i = 0; i < list.size(); i++) {
                    WikiCatalogDO item = list.get(i);
                    Long wikiId = item.getWikiId();
                    Long articleId = item.getArticleId();
                    String title = item.getTitle();
                    Integer level = item.getLevel();
                    Long parentId = item.getParentId();
                    Integer sort = item.getSort();
                    LocalDateTime createTime = item.getCreateTime();
                    LocalDateTime updateTime = item.getUpdateTime();
                    Boolean isDeleted = item.getIsDeleted();

                    sql.append("(")
                            .append(wikiId != null ? String.valueOf(wikiId) : "NULL").append(", ")
                            .append(articleId != null ? String.valueOf(articleId) : "NULL").append(", ")
                            .append(title != null ? "'" + escapeSql(title) + "'" : "NULL").append(", ")
                            .append(level != null ? String.valueOf(level) : "NULL").append(", ")
                            .append(parentId != null ? String.valueOf(parentId) : "NULL").append(", ")
                            .append(sort != null ? String.valueOf(sort) : "NULL").append(", ")
                            .append(createTime != null ? "'" + createTime.format(TIME_FORMATTER) + "'" : "NULL").append(", ")
                            .append(updateTime != null ? "'" + updateTime.format(TIME_FORMATTER) + "'" : "NULL").append(", ")
                            .append(isDeleted != null ? (isDeleted ? "'1'" : "'0'") : "0")
                            .append(")");

                    if (i < list.size() - 1) {
                        sql.append(", ");
                    }
                }

                return sql.toString();
            } catch (Exception e) {
                // 记录日志或抛出自定义异常
                throw new RuntimeException("Failed to generate SQL statement", e);
            }
        }

        private String escapeSql(String value) {
            // 简单的SQL转义函数，可以根据具体需求扩展
            return value.replace("'", "''");
        }
    }

    /**
     * 查询知识库目录中第一篇文章
     *
     * @param wikiId
     * @return
     */
    default WikiCatalogDO selectFirstArticleId(@Param("wikiId") Long wikiId) {
        return selectOne(Wrappers.<WikiCatalogDO>lambdaQuery()
                .eq(WikiCatalogDO::getWikiId, wikiId) // 查询指定知识库 id
                .eq(WikiCatalogDO::getLevel, WikiCatalogLevelEnum.TWO.getValue()) // 查询二级目录 二级目录才是文章的标题
                .isNotNull(WikiCatalogDO::getArticleId) // article_id 字段不能为空
                .orderByAsc(WikiCatalogDO::getId) // 按 id 增序排列 添加的时候就是id自增
                .last("LIMIT 1") // 仅查询一条
        );
    }

    /**
     * 根据知识库ID 以及文章ID查询对应的目录
     *
     * @param wikiId
     * @param articleId
     * @return WikiCatalogDO
     */
    default WikiCatalogDO selectByWikiIdAndArticleId(@Param("wikiId") Long wikiId, @Param("articleId") Long articleId) {
        return selectOne(Wrappers.<WikiCatalogDO>lambdaQuery()
                .eq(WikiCatalogDO::getWikiId, wikiId)
                .eq(WikiCatalogDO::getArticleId, articleId)
        );
    }

    /**
     * 查询指定知识库下指定文章的上一篇文章
     * @param wikiId
     * @param articleId
     * @return WikiCatalogDO
     */
    default WikiCatalogDO selectPreArticle(@Param("wikiId") Long wikiId, @Param("articleId") Long articleId) {
        return selectOne(Wrappers.<WikiCatalogDO>lambdaQuery()
                .eq(WikiCatalogDO::getWikiId, wikiId)
                .eq(WikiCatalogDO::getLevel, WikiCatalogLevelEnum.TWO.getValue()) //目录级别是2的时候
                .isNotNull(WikiCatalogDO::getArticleId) // article_id 字段不能为空
                .orderByAsc(WikiCatalogDO::getId) // 按 id 增序排列 添加的时候就是id自增
                .gt(WikiCatalogDO::getArticleId, articleId) // 查询比当前文章 ID 小的 (表明在当前文章的前一篇)
                .last("limit 1") // 第一条记录即为上一篇文章
        );
    }
    /**
     * 查询指定知识库下指定文章的下一篇文章
     * @param wikiId
     * @param articleId
     * @return WikiCatalogDO
     */

    default WikiCatalogDO selectNextArticle(@Param("wikiId") Long wikiId, @Param("articleId") Long articleId) {
        return selectOne(Wrappers.<WikiCatalogDO>lambdaQuery()
                .eq(WikiCatalogDO::getWikiId, wikiId)
                .eq(WikiCatalogDO::getLevel, WikiCatalogLevelEnum.TWO.getValue()) //目录级别是2的时候
                .isNotNull(WikiCatalogDO::getArticleId)//文章ID字段不能是null
                .orderByAsc(WikiCatalogDO::getId)
                .lt(WikiCatalogDO::getArticleId, articleId) // 查询比当前文章 ID 大的 (表明在当前文章的后一篇)
                .last("limit 1") // 第一条记录即为下一篇文章
        );
    }
}